package com.nfc.lock.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nfc.lock.common.exception.BusinessException;
import com.nfc.lock.common.result.ResultCode;
import com.nfc.lock.dto.request.RegionAddRequest;
import com.nfc.lock.entity.Region;
import com.nfc.lock.mapper.PowerRoomMapper;
import com.nfc.lock.mapper.RegionMapper;
import com.nfc.lock.security.SecurityUtils;
import com.nfc.lock.service.IRegionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

/**
 * Region service implementation.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements IRegionService {

    private final RegionMapper regionMapper;
    private final PowerRoomMapper powerRoomMapper;

    @Override
    public List<Region> getRegionTree(Long parentId) {
        Long actualParentId = parentId == null ? 0L : parentId;
        List<Region> regions = regionMapper.selectByParentId(actualParentId);
        for (Region region : regions) {
            region.setChildren(getRegionTree(region.getRegionId()));
        }
        return regions;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRegion(RegionAddRequest request) {
        Region parent = null;
        if (request.getParentId() != 0) {
            parent = regionMapper.selectById(request.getParentId());
            if (parent == null) {
                throw new BusinessException(ResultCode.REGION_NOT_EXIST);
            }
        }

        Region region = new Region();
        region.setRegionName(request.getRegionName());
        region.setRegionType(request.getRegionType());
        region.setParentId(request.getParentId());
        region.setCreateBy(SecurityUtils.getCurrentUserId());

        regionMapper.insert(region);

        String levelPath = parent != null
                ? parent.getLevelPath() + "/" + region.getRegionId()
                : region.getRegionId().toString();
        region.setLevelPath(levelPath);
        regionMapper.updateById(region);

        log.info("Region created successfully: {}", region.getRegionName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRegion(Long regionId, RegionAddRequest request) {
        Region region = regionMapper.selectById(regionId);
        if (region == null) {
            throw new BusinessException(ResultCode.REGION_NOT_EXIST);
        }

        region.setRegionName(request.getRegionName());
        regionMapper.updateById(region);

        log.info("Region updated successfully: {}", regionId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRegion(Long regionId) {
        Region region = regionMapper.selectById(regionId);
        if (region == null) {
            throw new BusinessException(ResultCode.REGION_NOT_EXIST);
        }

        if (regionMapper.countChildren(regionId) > 0) {
            throw new BusinessException(ResultCode.REGION_HAS_CHILDREN);
        }

        if (powerRoomMapper.countByRegionId(regionId) > 0) {
            throw new BusinessException(ResultCode.REGION_HAS_ROOMS);
        }

        regionMapper.deleteById(regionId);
        log.info("Region deleted successfully: {}", regionId);
    }

    @Override
    public List<Region> getChildrenRegions(Long parentId) {
        if (parentId == null) {
            return Collections.emptyList();
        }
        return regionMapper.selectByParentId(parentId);
    }
}